home *** CD-ROM | disk | FTP | other *** search
/ ASME's Mechanical Engine…ing Toolkit 1997 December / ASME's Mechanical Engineering Toolkit 1997 December.iso / c_lang / varinc.lzh / ORDBUILD.C < prev    next >
Text File  |  1979-11-30  |  24KB  |  522 lines

  1. /* SOURCE FILE: ORDBUILD.C */
  2. /*****************************************************************************/
  3. /* Functions for order-entry prompt screens and for saving data. These are   */
  4. /*   the middle-level functions that call the low-level display and prompt   */
  5. /*   functions to input screens of order data. They are in one source file   */
  6. /*   to permit order data in memory to be shared by them, but not by other   */
  7. /*   functions linked into the order-entry program.                          */
  8. /*****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <stddefs.h>
  12. #include "projutil.h"
  13. #include "ordentry.h"
  14.  
  15. /* Semiglobal data shared by functions in this source file only. */
  16. /* Data items are fields of an order. */
  17. SEMIGLOBAL char user[L_USER + 1] = "";
  18. SEMIGLOBAL char office[L_OFFICE + 1] = "";
  19. SEMIGLOBAL char cust_name[L_CUST_NAME + 1] = "";
  20. SEMIGLOBAL char company[L_COMPANY + 1] = "";
  21. SEMIGLOBAL char phone[L_PHONE + 1] = "";
  22. SEMIGLOBAL char ship_name[L_SHIP_NAME + 1] = "";
  23. SEMIGLOBAL char ship_cmpy[L_SHIP_CMPY + 1] = "";
  24. SEMIGLOBAL char ship_strt[L_SHIP_STRT + 1] = "";
  25. SEMIGLOBAL char ship_strt2[L_SHIP_STRT2 + 1] = "";
  26. SEMIGLOBAL char ship_city[L_SHIP_CITY + 1] = "";
  27. SEMIGLOBAL char ship_state[L_SHIP_STATE + 1] = "";
  28. SEMIGLOBAL char ship_zip[L_SHIP_ZIP + 1] = "";
  29. SEMIGLOBAL char bill_same[L_BILL_SAME + 1] = "y";
  30. SEMIGLOBAL char bill_name[L_BILL_NAME + 1] = "";
  31. SEMIGLOBAL char bill_cmpy[L_BILL_CMPY + 1] = "";
  32. SEMIGLOBAL char bill_strt[L_BILL_STRT + 1] = "";
  33. SEMIGLOBAL char bill_strt2[L_BILL_STRT2 + 1] = "";
  34. SEMIGLOBAL char bill_city[L_BILL_CITY + 1] = "";
  35. SEMIGLOBAL char bill_state[L_BILL_STATE + 1] = "";
  36. SEMIGLOBAL char bill_zip[L_BILL_ZIP + 1] = "";
  37. SEMIGLOBAL char is_resale[L_IS_RESALE + 1] = "n";
  38. SEMIGLOBAL char resale_id[L_RESALE_ID + 1] = "";
  39. SEMIGLOBAL char adv_ref[L_ADV_REF + 1] = "";
  40.  
  41. /* Variables "parts" and "part_descs" are 2-dimensional character arrays. */
  42. SEMIGLOBAL char parts[MAX_ITEMS][L_PARTS + 1] = {""};
  43. SEMIGLOBAL char part_descs[MAX_ITEMS][L_PART_DESC + 1] = {""};
  44.  
  45. SEMIGLOBAL long quantities[MAX_ITEMS] = {0};
  46. SEMIGLOBAL short ship_weights[MAX_ITEMS] = {0};
  47. SEMIGLOBAL short tot_weight = 0;
  48. SEMIGLOBAL money prices[MAX_ITEMS] = {0};
  49. SEMIGLOBAL money part_total = 0;
  50. SEMIGLOBAL char ship_car[L_SHIP_CAR + 1] = "";
  51. SEMIGLOBAL money ship_amt = 0;
  52. SEMIGLOBAL double inp_ship_amt = 0;
  53. SEMIGLOBAL double tax_pcnt = 0;
  54. SEMIGLOBAL money tax_amt = 0;
  55. SEMIGLOBAL char pay_terms[L_PAY_TERMS + 1] = "";
  56. SEMIGLOBAL char comment[L_COMMENT + 1] = "";
  57. SEMIGLOBAL byte last_part = 0;                /* index of last part on order */
  58.  
  59. /* Shared data not part of an order. */
  60. SEMIGLOBAL char scrn_title[] = "*** ENTER NEW ORDER ***";
  61.  
  62. /*****************************************************************************/
  63. /* id_user() identifies the user (salesperson or data-entry clerk). The user */
  64. /*   enters office code, name, and password. The password is then verified.  */
  65. /*****************************************************************************/
  66.  
  67. stepcode id_user()
  68.    {
  69.    IMPORT char user[];
  70.    IMPORT char office[];
  71.    IMPORT char scrn_title[];
  72.  
  73.    /* pw_find() is called to verify user and look up user data. */
  74.    flag pw_find(char *, char *, char *);  
  75.    char password[L_PASSWORD + 1];
  76.    stepcode step_rtn;
  77.    short ichar;
  78.  
  79.    /* Paint screen: Show headings for data to prompt for. */
  80.    beg_scrn("", scrn_title, "", "SALESPERSON");
  81.    tput(10, 20, "Office");
  82.    tput(12, 20, "Salesperson");
  83.    tput(14, 20, "Password");
  84.    do                          /* Loop until data entered or order canceled. */
  85.       {
  86.  
  87.       /* Input name of office seller is working in. */
  88.       step_rtn = prompt(office, "L", 3, L_OFFICE, MAND, 10, 32);
  89.       if (step_rtn == STEPBACK)
  90.          err_warn("Office must be supplied:", "");
  91.       }
  92.    while (step_rtn == STEPBACK);
  93.    if (step_rtn != STEPCANC)                             /* Prompt for user. */
  94.       do                       /* Loop until data entered or order canceled. */
  95.          {
  96.          user[0] = '\0';                         /* DON'T show last user id. */
  97.          step_rtn = prompt(user, "L", 2, L_USER, MAND, 12, 32);
  98.          if (step_rtn == STEPBACK)
  99.             err_warn("I must know who you are:", "");
  100.          }
  101.       while (step_rtn == STEPBACK);
  102.    if (step_rtn != STEPCANC)                 /* Input password without echo. */
  103.       {
  104.       CUR_MV(14, 32);
  105.       for (ichar = 0; ichar < L_PASSWORD && 
  106.          (password[ichar] = getch()) >= ' '; ++ichar)
  107.          ;
  108.       if (password[ichar] >= ' ')
  109.          ++ichar;
  110.       password[ichar] = '\0';
  111.       if (!pw_find(office, user, password))
  112.          {
  113.          err_warn("Access denied:", user); 
  114.          step_rtn = STEPCANC;
  115.          }
  116.       else                                          /* Display instructions. */
  117.          {
  118.          tput(17, 17, "Instructions for Commands Available at Prompts:");
  119.          tput(19, 20, "^R = (control-R) Re-prompt for previous.");
  120.          tput(20, 20, "^E = Erase data field, make it empty.");
  121.          tput(21, 20, "^X = Exit and cancel order.");
  122.          tput(23, 17, "Press ^X to exit, or another key to continue: _\b");
  123.          if (getch() == C_CANC)
  124.             step_rtn = STEPCANC;
  125.          }
  126.       }
  127.    return (step_rtn);
  128.    }
  129.  
  130. /*****************************************************************************/
  131. /* id_cust() prompts for customer identification information: customer name, */
  132. /*   company, phone, shipping/billing addresses, resale number, and          */
  133. /*   advertising reference.                                                  */
  134. /*****************************************************************************/
  135.  
  136. stepcode id_cust(step_rtn)
  137.  
  138.    /* If screen is backed into, step_rtn == STEPBACK; */
  139.    /*   otherwise step_rtn == STEPOK                  */
  140.    stepcode step_rtn;
  141.  
  142.    {
  143.  
  144.    /* Shared data accessed in this function. */
  145.    IMPORT char office[], user[], cust_name[], company[], ship_name[], 
  146.       ship_cmpy[], ship_strt[], ship_strt2[], ship_city[], ship_state[], 
  147.       ship_zip[], bill_name[], bill_cmpy[], bill_strt[], bill_strt2[], 
  148.       bill_city[], bill_state[], bill_zip[], adv_ref[], is_resale[], 
  149.       resale_id[], scrn_title[];
  150.    stepcode get_addr(stepcode, short, char[], char[], char[], 
  151.       char[], char[], char[], char[]);
  152.    void pnt_id_cust(void);
  153.    short step;
  154.  
  155.    /* Names of case labels for data-field prompts. */
  156.    enum prompts {NAME, COMPANY, PHONE, SHIP_ADDR, BILL_ADDR,
  157.       RESALE, ADV_REF, ENDSTEPS};
  158.  
  159.    /* Begin new screen. */
  160.    beg_scrn(user, scrn_title, office, "IDENTIFY");
  161.    pnt_id_cust();                                           /* Paint screen. */
  162.    tput(4, 30, cust_name);
  163.    tput(6, 30, company);
  164.  
  165.    /* Begin at last prompt if screen backed into. */
  166.    step = (step_rtn == STEPOK) ? 0 : (short)ENDSTEPS - 1;
  167.  
  168.    /* Note: (short) is a cast operator used to make a type short copy of the */
  169.    /*   value of the enum constant ENDSTEPS. Not using a cast gives a        */
  170.    /*   warning message.                                                     */
  171.  
  172.    /* Loop: Input each field of this screen. */
  173.    for (step_rtn = STEPOK; step_rtn != STEPCANC &&
  174.       (step < (short)ENDSTEPS) && (step >= 0); )
  175.       {
  176.       switch (step)                      /* Select next field to prompt for. */
  177.          {
  178.          case NAME:                                    /* Get customer name. */
  179.             step_rtn = prompt(cust_name, "L", 3, L_CUST_NAME, MAND, 4, 30);
  180.             break;
  181.          case COMPANY:                                  /* Get company name. */
  182.             step_rtn = prompt(company, "L", 3, L_COMPANY, OPT, 6, 30);
  183.             break;
  184.          case PHONE:                           /* Get customer phone number. */
  185.             step_rtn = prompt(phone, "P", 7, L_PHONE, OPT, 7, 30);
  186.             break;
  187.          case SHIP_ADDR:                          /* Get address to ship to. */
  188.             if (ship_name[0] == '\0')               /* No address input yet? */
  189.                {                       /* Then set default name and company. */
  190.                strcpy(ship_name, cust_name);
  191.                strcpy(ship_cmpy, company);
  192.                }
  193.  
  194.             /* Prompt for address data. Call get_addr(). */
  195.             step_rtn = get_addr(step_rtn, 9, ship_name, ship_cmpy, ship_strt,
  196.                ship_strt2, ship_city, ship_state, ship_zip);
  197.             break;
  198.          case BILL_ADDR:                     /* Get address to send bill to. */
  199.             tput(15, 30, "Bill same address? <y/n>    ");
  200.             step_rtn = prompt(bill_same, "Q", 1, L_BILL_SAME, MAND, 15, 56);
  201.             CUR_MV(15, 30);                             /* Move cursor to    */
  202.             CLR_LINE;                                   /*   erase question. */
  203.             if (step_rtn == STEPOK && strchr("Nn0", bill_same[0]))
  204.                step_rtn = get_addr(step_rtn, 15, bill_name, bill_cmpy, 
  205.                   bill_strt, bill_strt2, bill_city, bill_state, bill_zip);
  206.             else if (step_rtn == STEPOK)
  207.                bill_name[0] == '\0';                   /* Bill same address. */
  208.             break;
  209.          case RESALE:                             /* Is purchase for resale? */
  210.             step_rtn = prompt(is_resale, "Q", 1, L_IS_RESALE, MAND, 21, 25);
  211.             if (step_rtn == STEPOK && strchr("Yy1", is_resale[0]))
  212.                step_rtn = prompt(resale_id, "L", 3, L_RESALE_ID, OPT, 21, 53);
  213.             break;
  214.          case ADV_REF:               /* How did customer hear about product? */
  215.             step_rtn = prompt(adv_ref, "L", 1, L_ADV_REF, OPT, 23, 30);
  216.             break;
  217.          }
  218.  
  219.       /* Determine next step based on return from last one. */
  220.       if (step_rtn == STEPOK)                        /* Last was successful? */
  221.          ++step;                                 /* Yes; go on to next step. */
  222.       else if (step_rtn == STEPBACK)  
  223.          --step;                                /* No; back up to last step. */
  224.       }
  225.    return (step_rtn);
  226.    }
  227.  
  228. /*****************************************************************************/
  229. /* ord_itms() prompts repeatedly for part numbers and quantities of each     */
  230. /*    item ordered by customer. Displays price and shipping weight of each.  */
  231. /*****************************************************************************/
  232.  
  233. stepcode ord_itms(step_rtn)
  234. stepcode step_rtn;
  235.    {
  236.    IMPORT char user[], office[], scrn_title[];
  237.    IMPORT char parts[][L_PARTS + 1];
  238.    IMPORT char part_descs[][L_PART_DESC + 1];
  239.    IMPORT long quantities[];
  240.    IMPORT short ship_weights[];
  241.    IMPORT money prices[];
  242.    IMPORT byte last_part;
  243.    IMPORT money part_total;
  244.    flag inv_find(char[], char[], money *, short *);
  245.    short step;
  246.    char dbuf[14];             /* dummy string to pass to ftput() and ntput() */
  247.    byte ipart, part_cnt;
  248.    byte row;                                        /* line number on screen */
  249.    bflag part_found, more_items = YES;         /* part_found not initialized */
  250.    enum prompts {PART_NUM, QUANTITY, ENDSTEPS};
  251.  
  252.    /* Paint screen. */
  253.    beg_scrn(user, scrn_title, office, "ENTER ITEMS");
  254.    tput(4, 10, "Customer Name");
  255.    tput(4, 30, cust_name);
  256.    tput(6, 10, "Company Name");
  257.    tput(6, 30, company);
  258.    tput(9, 10, "Part Number      Description");
  259.    tput(9, 59, "Qty  Unit-Price");
  260.    tput(22, 51, "Order Total");
  261.    step = ipart = 0;                                 /* initializer for loop */
  262.    for (step_rtn = STEPOK; step_rtn != STEPCANC &&    
  263.       ipart < MAX_ITEMS && ipart >= 0 && more_items; )
  264.       {
  265.       row = ipart + 11;                                  /* row to prompt on */
  266.       switch (step)
  267.          {
  268.          case PART_NUM:                             /* Get next part number. */
  269.             do                           /* while part entered and not found */
  270.                {
  271.                step_rtn = prompt(parts[ipart], "L", 1, L_PARTS, OPT, row, 10);
  272.  
  273.                /* Got a part number and it checks out? */
  274.                part_found = (step_rtn == STEPOK) && inv_find(parts[ipart],
  275.                   part_descs[ipart], &prices[ipart], &ship_weights[ipart]);
  276.  
  277.                /* Check for end of order. */
  278.                if (step_rtn == STEPOK && parts[ipart][0] == '\0')
  279.                   more_items = NO;
  280.  
  281.                /* If part not found, then tell user. */
  282.                else if (!part_found && step_rtn == STEPOK)
  283.                   err_warn("No such part:", parts[ipart]);
  284.                else if (part_found)   /* Show description and price of part. */
  285.                   {
  286.                   tput(row, 27, part_descs[ipart]);
  287.                   tput(row, 64, "$");
  288.                   ftput(row, 65, (double) prices[ipart] / 100.0, 2, 
  289.                      dbuf, L_PRICES);
  290.  
  291.                   /* Default quantity is 1. */
  292.                   if (!quantities[ipart]) 
  293.                      quantities[ipart] = 1; 
  294.                   }
  295.  
  296.                /* Indent avoids confusion of do...while with while loop. */
  297.                } while (step_rtn == STEPOK && !part_found && more_items);      
  298.             break;
  299.          case QUANTITY:                    /* Get quantity for part ordered. */
  300.             step_rtn = nprompt(&quantities[ipart], 
  301.                "#", 0L, H_QUANTITY, MAND, row, 59);
  302.             break;
  303.          }
  304.       if (step_rtn == STEPOK)                     /* Update total on screen. */
  305.          {
  306.  
  307.          /* Has number of parts on this order increased? */
  308.          if (ipart > last_part && ipart < MAX_ITEMS && quantities[ipart] > 0)
  309.             last_part = ipart;                     /* Yes, add another part. */
  310.  
  311.          /* Sum the prices times quantities of parts ordered. */
  312.          for (part_total = part_cnt = 0; part_cnt <= last_part; ++part_cnt)
  313.             part_total += prices[part_cnt] * quantities[part_cnt];
  314.          tput(22, 64, "$");
  315.          ftput(22, 65, (double) part_total / 100.0, 2, dbuf, L_PRICES);
  316.          }
  317.  
  318.       /* Determine next part to prompt for and next step. */
  319.       if (step == (short)PART_NUM)                /* Just got a part number. */
  320.          {
  321.          step = (short)QUANTITY;                     /* Next get a quantity. */
  322.          if (step_rtn == STEPBACK)
  323.             --ipart;
  324.          }
  325.       else                                           /* Just got a quantity. */
  326.          {
  327.          step = (short)PART_NUM;                  /* Next get a part number. */
  328.          if (step_rtn == STEPOK)
  329.           ++ipart;
  330.          }
  331.       }
  332.    return (step_rtn);
  333.    }
  334.  
  335. /*****************************************************************************/
  336. /* ship_pay() prompts for shipping carrier, shipping charges, sales-tax      */
  337. /*   rate, and payment terms. Input these data after items are entered.      */
  338. /*****************************************************************************/
  339.  
  340. stepcode ship_pay(step_rtn)
  341.  
  342.    /* If screen is backed into, step_rtn == STEPBACK; */
  343.    /*   otherwise step_rtn == STEPOK.                 */
  344.    stepcode step_rtn;
  345.    {
  346.    IMPORT char office[], user[], cust_name[], company[],
  347.       ship_car[], pay_terms[], comment[], scrn_title[];
  348.    IMPORT money part_total, tax_amt, ship_amt;
  349.    IMPORT double inp_ship_amt, tax_pcnt;
  350.    IMPORT char is_resale[];                       /* Yes means no sales tax. */
  351.    IMPORT byte last_part;
  352.    IMPORT short ship_weights[];
  353.    IMPORT short tot_weight;
  354.    short step;
  355.    char dbuf[14];
  356.    byte ipart;
  357.    enum prompts {SHIP_CAR, SHIP_AMT, TAX, PAY_TERMS, COMMENT, ENDSTEPS};
  358.  
  359.    /* Verify that something has been ordered; else return STEPBACK. */
  360.    if (quantities[0] == 0 || parts[0][0] == '\0')
  361.       {
  362.       err_warn("Nothing ordered:", "");                  /* Give diagnostic. */
  363.       return (STEPBACK);                      /* Back up to previous screen. */
  364.       }
  365.  
  366.    /* Begin new screen. */
  367.    beg_scrn(user, scrn_title, office, "SHIP, TAX, PAY");
  368.    pnt_ship_pay();                                          /* Paint screen. */
  369.    tput(4, 30, cust_name);
  370.    tput(6, 30, company);
  371.  
  372.    /* Sum ship weights and show total (weights in ounces). */
  373.    for (ipart = tot_weight = 0; ipart <= last_part; ++ipart)
  374.       tot_weight += ship_weights[ipart];
  375.    ntput(9, 30, (long) tot_weight, dbuf, 10);         /* Show total weight. */
  376.  
  377.    /* Begin at last prompt if screen backed into. */
  378.    step = (step_rtn == STEPOK) ? 0 : (short)ENDSTEPS - 1;
  379.    for (step_rtn = STEPOK; step_rtn != STEPCANC && 
  380.       (step < (short) ENDSTEPS) && step >= 0; )
  381.       {
  382.       switch (step)
  383.          {
  384.          case SHIP_CAR:                             /* Get shipping carrier. */
  385.             step_rtn = prompt(ship_car, "L", 1, L_SHIP_CAR, OPT, 11, 30);
  386.             break;
  387.  
  388.          case SHIP_AMT:                          /* Get shipping charges, if */
  389.             if (ship_car[0] != '\0')             /*   a carrier was entered. */
  390.                step_rtn = fprompt(&inp_ship_amt, "F", 20, 
  391.                   H_SHIP_AMT, 11, 2, OPT, 11, 65);
  392.                ship_amt = (money) (inp_ship_amt * 100.0);
  393.             break;
  394.          case TAX:                              /* Get sales-tax percentage. */
  395.  
  396.             /* If sale is for resale, then don't add sales tax. */
  397.             if (strchr("Yy1", is_resale[0]))
  398.                tax_pcnt = 0.0;
  399.             else                       /* Prompt for local tax rate, if any. */
  400.                step_rtn = fprompt(&tax_pcnt, "F", 0, 
  401.                   H_TAX_PCNT, 4, 1, OPT, 14, 30);
  402.             if (step_rtn == STEPOK)
  403.                tax_amt = (tax_pcnt * part_total) / 100;
  404.             tput(14, 64, "$");
  405.             ftput(14, 65, (double) tax_amt / 100.0, 2, dbuf, L_TAX_AMT);
  406.             ftput(18, 65, (double) part_total / 100.0, 2, dbuf, L_PRICES);
  407.             ftput(20, 65, (double) (part_total + tax_amt + ship_amt) / 100.0, 
  408.                2, dbuf, L_PRICES);  
  409.             break;
  410.          case PAY_TERMS:                          /* Get payment terms code. */
  411.             step_rtn = prompt(pay_terms, "L", 1, L_PAY_TERMS, MAND, 17, 30);
  412.             break;
  413.          case COMMENT:                        /* Get order comment (if any). */
  414.             step_rtn = prompt(comment, "L", 1, L_COMMENT, OPT, 22, 11);
  415.             break;
  416.          }
  417.  
  418.       /* Determine next step based on return from last one. */
  419.       if (step_rtn == STEPOK)                        /* Last was successful? */
  420.          ++step;                                 /* Yes; go on to next step. */
  421.       else if (step_rtn == STEPBACK)  
  422.          --step;                                /* No; back up to last step. */
  423.       }
  424.    return (step_rtn);
  425.    }
  426.  
  427. /*****************************************************************************/
  428. /* wrt_ord() writes an order to standard output after asking if all is OK.   */
  429. /* The order number is assigned from a counter.                              */
  430. /*****************************************************************************/
  431.  
  432. /*  File data to be output are written to the standard output file (stdout). */
  433. /*    This permits data to be redirected at the command line. For example:   */
  434. /*      ORDENTRY > SS841225.ORD        Creates new file;                     */
  435. /*                                       note date encoded in name.          */
  436. /*      ORDENTRY >> NEWORDS.DAT        Appends data to file.                 */
  437. /*      ORDENTRY | ORDSAVE | ORDPRINT  Serves as source for a pipeline.      */
  438. /*                                                                           */
  439. /*  This standard file use scheme gives flexibility in the way the program   */
  440. /*    may be used. Text and control characters are output to the standard    */
  441. /*    error file (stderr), so they won't appear in the redirected output.    */
  442.  
  443. stepcode wrt_ord()
  444.    {
  445.  
  446.    /* IMPORT all the fields of the order. */
  447.    IMPORT char office[], user[], cust_name[], company[], ship_name[], 
  448.       ship_cmpy[], ship_strt[], ship_strt2[], ship_city[], ship_state[], 
  449.       ship_zip[], bill_name[], bill_cmpy[], bill_strt[], bill_strt2[], 
  450.       bill_city[], bill_state[], bill_zip[], adv_ref[], resale_id[];
  451.    IMPORT char is_resale[];                       /* Yes means no sales tax. */
  452.    IMPORT char parts[][L_PARTS + 1];
  453.    IMPORT long quantities[];
  454.    IMPORT money prices[];
  455.    IMPORT byte last_part;
  456.    IMPORT short tot_weight;
  457.    IMPORT char ship_car[], pay_terms[], comment[];
  458.    IMPORT money part_total, tax_amt, ship_amt;
  459.    IMPORT long order_num(void);
  460.    long order_id;                          /* order number, from order_num() */
  461.    long long_time;                               /* time of day, from time() */
  462.    byte ipart;
  463.    char is_ok[2];                             /* Are data OK? message buffer */
  464.    char log_buf[80];                         /* buffer for logentry() string */
  465.    stepcode step_rtn;
  466.  
  467.    /* Ask if order is OK. */
  468.    tput(23, 2, "Is order OK? <y/n>  _ ");
  469.    strcpy(is_ok, "y");                                    /* Default is yes. */
  470.    step_rtn = prompt(is_ok, "Q", 1, 1, MAND, 23, 22);
  471.    if (step_rtn != STEPOK)
  472.       return (step_rtn);
  473.    else if (0 != strchr("Nn0", is_ok[0]))
  474.       return (STEPBACK);
  475.  
  476.    /* Write order data to standard output. Each line begins with */
  477.    /*   two uppercase characters or numbers that indicate the    */
  478.    /*   meaning of that data item.                               */
  479.    order_id = order_num();
  480.    sprintf(log_buf, "ORD %ld, SL %s, TL %ld", order_id, user, part_total);
  481.    logentry(log_buf);                /* Record order in log file as an audit */
  482.                                      /*   trail for sales and commissions.   */
  483.  
  484.  
  485.    printf("\nBEGIN ORDER %ld\n", order_id);
  486.    time(&long_time);                           /* Get time of day as a long. */
  487.    printf("TM %s", ctime(&long_time));                  /* Save time of day. */
  488.  
  489.    printf("OF %s\nSL %s\nCN %s\nCO %s\n", office, user, cust_name, company);
  490.    printf("SN %s\nSC %s\nST %s\n", ship_name, ship_cmpy, ship_strt);
  491.    if (ship_strt2[0] != '\0')
  492.       printf("S2 %s\n", ship_strt2);
  493.    printf("SY %s\nSS %s\nSZ %s\n", ship_city, ship_state, ship_zip); 
  494.  
  495.    if (bill_name[0] != '\0')           /* Save billing address if different. */
  496.       {
  497.       printf("BN %s\nBC %s\nBT %s\n", bill_name, bill_cmpy, bill_strt);
  498.       if (bill_strt2[0] != '\0')
  499.          printf("B2 %s\n", bill_strt2);
  500.       printf("BY %s\nBS %s\nBZ %s\n", bill_city, bill_state, bill_zip); 
  501.       }
  502.  
  503.    if (strchr("Yy1", is_resale[0]))                  /* Is order for resale? */
  504.       printf("RS %s\n", resale_id);                  /* Yes; save resale_id. */
  505.  
  506.    /* List each part, quantity, and price. */
  507.    for (ipart = 0; ipart <= last_part && quantities[ipart]; ++ipart)
  508.       printf("PN %s\nQY %ld\nPR %ld\n", parts[ipart], 
  509.          quantities[ipart], prices[ipart]);
  510.    printf("TL %ld\nTX %ld\nSH %s\nSA %ld\nWT %d\n", part_total,
  511.       tax_amt, ship_car, ship_amt, tot_weight);
  512.  
  513.    if (adv_ref[0] != '\0')
  514.       printf("AD %s\n", adv_ref);
  515.    printf("PA %s\n", pay_terms);
  516.    if (comment[0] != '\0')
  517.       printf("CM %s\n", comment);
  518.    printf("END ORDER %ld\n", order_id);
  519.    return (STEPOK);
  520.    }
  521.  
  522.